package main

import (
	"context"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"os/exec"
	_ "strings"
	"time"

	"golang.org/x/oauth2"
	"golang.org/x/oauth2/microsoft"
)

type OnSection struct {
	id                   string
	self                 string
	createdDateTime      string
	displayName          string
	lastModifiedDateTime string
	pagesUrl             string

	// other, ignore
}

type CodeSrvCbk struct {
	sch chan url.Values
}

func (cs *CodeSrvCbk) ServeHTTP(rspw http.ResponseWriter, rq *http.Request) {

	fmt.Println("req:", rq.URL.Path)

	if rq.URL.Path == "/note2wiki" {
		rspw.WriteHeader(http.StatusOK)
		fmt.Fprintf(rspw, "Hello, end")

		rq.ParseForm()
		cs.sch <- rq.Form

		//fmt.Println("f:", rq.Form)

	} else {
		rspw.WriteHeader(http.StatusNotFound)
	}
}

func DumpRemote(ct *http.Client, uss string) {

	jsn, err := ct.Get(uss)
	if err != nil {
		log.Fatal(err)
	}

	/**/
	fmt.Println("s:", jsn.Status)
	kkk, err := io.ReadAll(jsn.Body)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("body:", string(kkk))
}

func main() {
	var ss url.Values
	var sec OnSection

	sch := make(chan url.Values, 16)

	/* server http */
	go http.ListenAndServe(":8181", &CodeSrvCbk{sch})

	/**/
	conf := &oauth2.Config{
		ClientID: "7639a675-fb5d-401a-b671-e8a849804b17",
		Scopes:   []string{"User.Read", "Notes.Read"},
		Endpoint: microsoft.AzureADEndpoint("consumers"),
	}

	aurl := conf.AuthCodeURL("11223344", oauth2.ApprovalForce)

	//aurl = strings.ReplaceAll(aurl, "&", "^&")
	//cmm := exec.Command("/mnt/c/Windows/System32/cmd.exe", "/C", "start", "msedge", aurl)
	cmm := exec.Command("xdg-open", aurl)
	err := cmm.Run()
	if err != nil {
		fmt.Println("exec msedge, ", err)
		return
	}

	// fmt.Println("::", aurl)
	select {
	case <-time.After(30 * time.Second):
		fmt.Println("time out, 30s")
		return

	case ss = <-sch:
		fmt.Println("from:", ss)
	}

	/**/
	if ss.Get("error") != "" {
		fmt.Println("user deny..")
		return
	}

	httpClient := &http.Client{Timeout: 2 * time.Second}
	ctx := context.Background()
	ctx = context.WithValue(ctx, oauth2.HTTPClient, httpClient)

	tok, err := conf.Exchange(ctx, ss.Get("code"))
	if err != nil {
		log.Fatal(err)
	}

	/**/
	fmt.Println("access token:", tok.AccessToken)
	fmt.Println("refres token:", tok.RefreshToken)
	fmt.Println("Expiry time:", tok.Expiry)

	/**/
	client := conf.Client(ctx, tok)

	DumpRemote(client, "https://graph.microsoft.com/v1.0/me/")

	/**/
	secs, err := client.Get("https://graph.microsoft.com/v1.0/me/onenote/sections")
	if err != nil {
		return
	}

	defer secs.Body.Close()

	jsn := json.NewDecoder(secs.Body)

	/**/
	tk, err := jsn.Token()
	if err != nil {
		return
	}

	fmt.Println("tk0:", tk)

	tk, err = jsn.Token()
	if err != nil {
		return
	}

	fmt.Println("tk1:", tk)

	tk, err = jsn.Token()
	if err != nil {
		return
	}

	fmt.Println("tk2:", tk)

	tk, err = jsn.Token()
	if err != nil {
		return
	}

	fmt.Println("tk3:", tk)

	tk, err = jsn.Token()
	if err != nil {
		return
	}

	fmt.Println("tk3:", tk)

	/**/
	err = jsn.Decode(&sec)
	if err != nil {
		fmt.Println("sec, decode, fail:", err)
		return
	}
	fmt.Println("id0:", sec.id)

	err = jsn.Decode(&sec)
	if err != nil {
		fmt.Println("sec, decode, fail:", err)
		return
	}
	fmt.Println("id1:", sec.id)

	return
}
